
package database;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import org.Globals;

import android.content.Context;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteOpenHelper;
import android.os.Environment;
import android.util.Log;


public class DatabaseHelper extends SQLiteOpenHelper {

	// The Android's default system path of your application database.
	// private static String DB_PATH = "/data/data/YOUR_PACKAGE/databases/";
	// private static String DB_PATH = "databases/";

	private static String DB_NAME = "ga";
	private static String DB_FILE_NAME = DB_NAME + ".sqlite";
	public static String dbPath;

	protected SQLiteDatabase db = null;

	private final Context myContext;
	private static DatabaseHelper mInstance = null;

	/**
	 * Constructor Takes and keeps a reference of the passed context in order to
	 * access to the application assets and resources.
	 * 
	 * Constructor should be private to prevent direct instantiation. make call
	 * to static factory method "getInstance()" instead.
	 * 
	 * @param context
	 */
	private DatabaseHelper(Context context) {

		super(context, DB_NAME, null, 1);
		this.myContext = context;
		dbPath = "/Android/data/" + Globals.packageName(myContext)
				+ "/databases/";
	}

	public static DatabaseHelper getInstance(Context ctx) {
		/**
		 * use the application context as suggested by CommonsWare. this will
		 * ensure that you dont accidentally leak an Activitys context (see this
		 * article for more information:
		 * http://developer.android.com/resources/articles
		 * /avoiding-memory-leaks.html)
		 */
		if (mInstance == null) {
			mInstance = new DatabaseHelper(ctx.getApplicationContext());
		}
		return mInstance;
	}

	/**
	 * Creates a empty database on the system and rewrites it with your own
	 * database.
	 * */
	private void createDataBase() throws IOException {

		boolean dbExist = checkDataBase();

		if (dbExist) {
			Log.d("ConceptWave", "DB already exists");
			// do nothing - database already exist
		} else {
			Log.d("ConceptWave", "Creating a new DB");
			// By calling this method and empty database will be created into
			// the default system path
			// of your application so we are gonna be able to overwrite that
			// database with our database.
			this.getReadableDatabase();

			try {
				copyDataBase();
			} catch (IOException e) {
				e.printStackTrace();

				throw new Error("Error copying database");
			}
		}
	}

	/**
	 * Check if the database already exist to avoid re-copying the file each
	 * time you open the application.
	 * 
	 * @return true if it exists, false if it doesn't
	 */
	private boolean checkDataBase() {

		SQLiteDatabase checkDB = null;

		try {
			// String myPath = DB_PATH + DB_NAME;
			// String myPath = myContext.getFilesDir().getAbsolutePath() +
			// DB_PATH + DB_NAME;
			// String myPath = myContext.getDatabasePath(DB_NAME)
			// .getAbsolutePath();
			String myPath = getDatabasePath() + DB_NAME;
			checkDB = SQLiteDatabase.openDatabase(myPath, null,
					SQLiteDatabase.OPEN_READWRITE);

		} catch (SQLiteException e) {
			// e.printStackTrace();
			// database does't exist yet.
		}

		if (checkDB != null) {
			checkDB.close();
		}

		return checkDB != null ? true : false;
	}

	/**
	 * Copies your database from your local assets-folder to the just created
	 * empty database in the system folder, from where it can be accessed and
	 * handled. This is done by transfering bytestream.
	 * */
	private void copyDataBase() throws IOException {
		Log.d("ConceptWave", "Copying DB from asset");

		// Open your local db as the input stream
		InputStream myInput = myContext.getAssets().open(DB_FILE_NAME);

		// Path to the just created empty db
		// String outFileName = DB_PATH + DB_NAME;
		String outFileName = getDatabasePath() + DB_NAME;
		Log.d("ConceptWave", "DB Output Path: " + outFileName);

		// Open the empty db as the output stream
		OutputStream myOutput = new FileOutputStream(outFileName);

		// transfer bytes from the inputfile to the outputfile
		byte[] buffer = new byte[1024];
		int length;
		while ((length = myInput.read(buffer)) > 0) {
			myOutput.write(buffer, 0, length);
		}

		// Close the streams
		myOutput.flush();
		myOutput.close();
		myInput.close();
	}

	public SQLiteDatabase openDataBase() throws SQLException, IOException {

		if (db == null) {
			// Create DB if not already created
			createDataBase();

			Log.d("ConceptWave", "Open DB");
			// Open the database
			// String myPath = DB_PATH + DB_NAME;
			// String myPath = myContext.getFilesDir().getAbsolutePath() +
			// DB_PATH +
			// DB_NAME;
			// String myPath = myContext.getDatabasePath(DB_NAME)
			// .getAbsolutePath();
			String myPath = getDatabasePath() + DB_NAME;
			db = SQLiteDatabase.openDatabase(myPath, null,
					SQLiteDatabase.OPEN_READWRITE);
		}

		return db;
	}

	private String getDatabasePath() {
		String cachePath;
		File cacheDir;
		// Choose chache directory
		if (android.os.Environment.getExternalStorageState().equals(
				android.os.Environment.MEDIA_MOUNTED)) {
			cachePath = Environment.getExternalStorageDirectory()
					.getAbsolutePath() + dbPath;
			cacheDir = new File(cachePath);
			if (!cacheDir.exists()) {
				Log.d("ReyOfLight", "creating dir " + cachePath);
				boolean status = cacheDir.mkdirs();
				Log.d("ReyOfLight", "status: " + status);
			}
		} else
			cachePath = myContext.getFilesDir().getAbsolutePath()
					.replace("files", "databases/");

		return cachePath;

	}

	@Override
	public synchronized void close() {

		if (db != null)
			db.close();

		db = null;

		super.close();
	}

	@Override
	public void onCreate(SQLiteDatabase db) {

	}

	@Override
	public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

	}

	// Add your public helper methods to access and get content from the
	// database.
	// You could return cursors by doing "return myDataBase.query(....)" so it'd
	// be easy
	// to you to create adapters for your views.

}
